import markdown
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.html import strip_tags
from django.utils.safestring import mark_safe
from django.core.exceptions import ValidationError
from django.contrib.postgres.indexes import GinIndex
from account.models import CustomUser as User
from markdownx.models import MarkdownxField
from django.db.models.signals import pre_save
from django.utils.text import slugify
from django.dispatch import receiver
from django.utils import timezone


class Category(models.Model):
    """分类模型"""
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    description = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'category'
        verbose_name = '分类管理'
        verbose_name_plural = '分类管理'

    def __str__(self):
        return self.name


class Tag(models.Model):
    """标签模型"""
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    description = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'tag'
        verbose_name = '标签管理'
        verbose_name_plural = '标签管理'

    def __str__(self):
        # 返回对象的名称
        return self.name


class Article(models.Model):
    """博客模型"""
    STATUS_DRAFT = 0
    STATUS_PUBLISHED = 1
    STATUS_REVIEW = 2
    STATUS_OFFLINE = 3
    STATUS_CHOICES = (
        (STATUS_DRAFT, '草稿'),
        (STATUS_PUBLISHED, '发布'),
        (STATUS_REVIEW, '审核中'),
        (STATUS_OFFLINE, '下架'),
    )

    SOURCE_ORIGINAL = 1
    SOURCE_REPRINT = 2
    SOURCE_TRANSLATION = 3
    SOURCE_TYPE_CHOICES = (
        (SOURCE_ORIGINAL, '原创'),
        (SOURCE_REPRINT, '转载'),
        (SOURCE_TRANSLATION, '翻译'),
    )
    # 文章类型
    ARTICLE_CHOICES = [
        (1, '推荐'),
        (2, '付费专栏'),
        (3, 'VIP文章'),
    ]
    id = models.BigAutoField(primary_key=True)
    title = models.CharField(
        verbose_name="标题",
        max_length=30,
        # 可选增强配置
        db_index=True,  # 添加数据库索引
        blank=False,  # 禁止空值
        null=False,  # 禁止数据库空值
        help_text="请输入文章标题（最多30个字符）",
        error_messages={
            'null': _("标题不能为空"),
            'blank': _("标题不能为空"),
            'max_length': _("标题长度不能超过30个字符"),
            'unique': _("标题已存在，请勿重复")
        }
    )
    slug = models.SlugField(max_length=200, blank=True, null=True, unique=False, verbose_name='URL标识')
    content = MarkdownxField(
        verbose_name='内容',
        help_text='Markdown格式内容',
        # 添加MySQL专用参数
        db_collation='utf8mb4_general_ci',
        # db_index_length=200  # 为MySQL指定索引前缀长度
    )  # Markdown

    author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='作者')

    category = models.ForeignKey(
        Category,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name='分类'
    )
    status = models.SmallIntegerField(
        choices=STATUS_CHOICES,
        default=STATUS_DRAFT,
        verbose_name='状态'
    )
    is_top = models.BooleanField(default=False, verbose_name='是否置顶')

    views = models.PositiveIntegerField(default=0, verbose_name='浏览量')
    likes = models.PositiveIntegerField(default=0, verbose_name='点赞量')
    collects = models.PositiveIntegerField(default=0, verbose_name='收藏数')

    comments = models.IntegerField(default=0, verbose_name='评论数')
    # 多对多关系（通过中间表）
    likes_counts = models.ManyToManyField(
        User,
        through='UserLike',
        related_name='liked_posts'  # 用户反向查询：user.liked_posts
    )
    bookmarks = models.ManyToManyField(
        User,
        through='UserBookmark',
        related_name='bookmarked_posts'  # 用户反向查询：user.bookmarked_posts
    )
    cover = models.ImageField(upload_to='covers/', verbose_name='封面图')
    tags = models.ManyToManyField(Tag, blank=True, verbose_name='标签')
    article_type = models.SmallIntegerField(
        choices=ARTICLE_CHOICES,
        default=1,
        verbose_name='文章类型'
    )
    published_time = models.DateTimeField(null=True, blank=True, verbose_name='发布时间')
    created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    source_type = models.SmallIntegerField(
        choices=SOURCE_TYPE_CHOICES,
        default=SOURCE_ORIGINAL,
        verbose_name='来源类型'
    )
    source_url = models.URLField(
        max_length=500,
        default='',
        blank=True,
        verbose_name='原文链接'
    )

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章管理'
        indexes = [
            models.Index(fields=['-published_time'], name='pub_date_desc_index'),
            models.Index(fields=['author', 'status'], name='author_status_index'),
            # models.Index(fields=['content(200)'], name='content_prefix_idx'),
        ]
        ordering = ['-is_top', '-published_time']

    def __str__(self):
        return self.title


@receiver(pre_save, sender=Article)
def pre_save_receiver(sender, instance, **kwargs):
    if not instance.slug:
        # 使用作者用户名和作者账号创建时间生成slug
        author_joined_date = instance.author.date_joined.strftime('%Y%m%d%H%M%S')
        author_name = instance.author.username
        instance.slug = f"{author_name}-{author_joined_date}"


class UserLike(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Article, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)  # 点赞时间

    class Meta:
        db_table = 'user_like'  # 指定表名
        verbose_name = '用户点赞'
        verbose_name_plural = '用户点赞管理'
        # 联合唯一约束：防止重复点赞
        unique_together = ('user', 'post')  # 唯一约束：防止重复点赞


class UserBookmark(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Article, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)  # 收藏时间

    class Meta:
        db_table = 'user_bookmark'  # 指定表名
        verbose_name = '用户收藏'
        verbose_name_plural = '用户收藏管理'
        unique_together = ('user', 'post')  # 唯一约束：防止重复收藏
